#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""告警管理API路由模块"""

from flask import Blueprint, request, jsonify
from datetime import datetime, timedelta
from functools import wraps
import logging

# 导入告警管理和数据库服务
from alerts import alert_manager, AlertType, SeverityLevel
from database import get_db_service
from .auth import token_required

# 创建蓝图
alerts_bp = Blueprint('alerts', __name__, url_prefix='/api/alerts')

# 获取数据库服务实例
db_service = get_db_service()

# 配置日志
logger = logging.getLogger(__name__)


def log_api_access(f):
    """记录API访问的装饰器"""
    @wraps(f)
    def decorated(*args, **kwargs):
        logger.info(f"API访问: {request.method} {request.path}")
        return f(*args, **kwargs)
    return decorated


@alerts_bp.route('/', methods=['GET'])
@token_required
@log_api_access
def get_alerts():
    """获取告警列表
    
    查询参数:
    - page: 页码，默认1
    - per_page: 每页数量，默认20
    - status: 告警状态(filter, confirmed, resolved)
    - severity: 严重程度(low, medium, high, critical)
    - type: 告警类型(pedestrian_violation, zone_violation, wrong_direction, parking_violation, vehicle_overlap, system_warning)
    - camera_id: 摄像头ID
    - start_time: 开始时间(ISO格式)
    - end_time: 结束时间(ISO格式)
    - unread_only: 是否只显示未读告警，默认false
    """
    try:
        # 解析查询参数
        page = int(request.args.get('page', 1))
        per_page = int(request.args.get('per_page', 20))
        status = request.args.get('status')
        severity = request.args.get('severity')
        alert_type = request.args.get('type')
        camera_id = request.args.get('camera_id')
        start_time = request.args.get('start_time')
        end_time = request.args.get('end_time')
        unread_only = request.args.get('unread_only', 'false').lower() == 'true'
        
        # 构建过滤条件
        filters = {}
        if status:
            filters['status'] = status
        if severity:
            filters['severity'] = severity
        if alert_type:
            filters['type'] = alert_type
        if camera_id:
            filters['camera_id'] = int(camera_id)
        if start_time:
            filters['start_time'] = datetime.fromisoformat(start_time)
        if end_time:
            filters['end_time'] = datetime.fromisoformat(end_time)
        
        # 获取告警列表
        alerts, total = db_service.get_alerts(
            page=page,
            per_page=per_page,
            filters=filters,
            unread_only=unread_only
        )
        
        # 格式化告警数据
        alert_list = []
        for alert in alerts:
            alert_list.append({
                'id': alert.id,
                'type': alert.type,
                'type_name': AlertType.get_alert_name(alert.type),
                'severity': alert.severity,
                'severity_name': SeverityLevel.get_level_name(alert.severity),
                'camera_id': alert.camera_id,
                'camera_name': alert.camera.name if alert.camera else None,
                'location': alert.location,
                'message': alert.message,
                'status': alert.status,
                'created_at': alert.created_at.isoformat() if alert.created_at else None,
                'updated_at': alert.updated_at.isoformat() if alert.updated_at else None,
                'confirmed_at': alert.confirmed_at.isoformat() if alert.confirmed_at else None,
                'resolved_at': alert.resolved_at.isoformat() if alert.resolved_at else None,
                'is_read': alert.is_acknowledged,
                'related_violation_id': alert.related_violation_id,
                'image_path': alert.image_path,
                'metadata': alert.metadata
            })
        
        return jsonify({
            'success': True,
            'data': {
                'alerts': alert_list,
                'pagination': {
                    'page': page,
                    'per_page': per_page,
                    'total': total,
                    'total_pages': (total + per_page - 1) // per_page
                }
            },
            'message': '告警列表获取成功'
        })
        
    except Exception as e:
        logger.error(f"获取告警列表失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'获取告警列表失败: {str(e)}'
        }), 500


@alerts_bp.route('/<int:alert_id>', methods=['GET'])
@token_required
@log_api_access
def get_alert_detail(alert_id):
    """获取单个告警详情"""
    try:
        # 获取告警信息 - 确保返回的是字典格式
        alert_dict = db_service.get_alert_by_id(alert_id)
        if not alert_dict:
            return jsonify({
                'success': False,
                'data': None,
                'message': '告警不存在'
            }), 404
        
        # 确保alert是字典格式，不直接使用任何ORM对象
        if not isinstance(alert_dict, dict):
            raise ValueError(f"期望返回字典格式，但得到了{type(alert_dict).__name__}")
        
        # 标记为已确认
        if not alert_dict.get('is_acknowledged'):
            db_service.update_alert_acknowledged_status(alert_id, True)
        
        # 构建响应数据 - 只使用字典的get方法
        alert_data = {
            'id': alert_dict.get('id'),
            'type': alert_dict.get('alert_type'),
            'type_name': AlertType.get_alert_name(alert_dict.get('alert_type')) if alert_dict.get('alert_type') else None,
            'severity': alert_dict.get('severity'),
            'severity_name': SeverityLevel.get_level_name(alert_dict.get('severity')) if alert_dict.get('severity') else None,
            'severity_color': SeverityLevel.get_level_color(alert_dict.get('severity')) if alert_dict.get('severity') else None,
            'source': alert_dict.get('source'),
            'message': alert_dict.get('message'),
            'details': alert_dict.get('details'),
            'snapshot_path': alert_dict.get('snapshot_path'),
            'violation_id': alert_dict.get('violation_id'),
            'is_acknowledged': alert_dict.get('is_acknowledged'),
            'acknowledged_by': alert_dict.get('acknowledged_by'),
            'acknowledged_at': alert_dict.get('acknowledged_at'),
            'is_resolved': alert_dict.get('is_resolved'),
            'resolved_at': alert_dict.get('resolved_at'),
            'created_at': alert_dict.get('created_at'),
            'is_read': alert_dict.get('is_acknowledged'),
            'related_violation': None,
            'history': []
        }
        
        # 获取关联的违规记录 - 只使用字典格式处理
        violation_id = alert_dict.get('violation_id')
        if violation_id:
            try:
                violation_result = db_service.get_violation_by_id(violation_id)
                if violation_result and isinstance(violation_result, dict):
                    alert_data['related_violation'] = {
                        'id': violation_result.get('id'),
                        'type': violation_result.get('violation_type'),
                        'camera_id': violation_result.get('camera_id'),
                        'created_at': violation_result.get('created_at')
                    }
            except Exception as violation_error:
                logging.warning(f"获取关联违规记录时出错: {str(violation_error)}")
        
        # 获取告警历史记录 - 只使用字典格式处理
        try:
            history_records = db_service.get_alert_history(alert_id)
            if history_records and isinstance(history_records, list):
                for record in history_records:
                    if isinstance(record, dict):
                        alert_data['history'].append({
                            'id': record.get('id'),
                            'action': record.get('action'),
                            'user_id': record.get('user_id'),
                            'user_name': record.get('user_name') or (record.get('user') and record.get('user').get('username')),
                            'comment': record.get('comment'),
                            'timestamp': record.get('timestamp')
                        })
        except Exception as history_error:
            logging.warning(f"获取告警历史记录时出错: {str(history_error)}")
        
        return jsonify({
            'success': True,
            'data': alert_data,
            'message': '告警详情获取成功'
        })
        
    except Exception as e:
        logger.error(f"获取告警详情失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'获取告警详情失败: {str(e)}'
        }), 500


@alerts_bp.route('/<int:alert_id>/confirm', methods=['POST'])
@token_required
@log_api_access
def confirm_alert(alert_id):
    """确认告警"""
    try:
        # 解析请求体
        data = request.get_json() or {}
        comment = data.get('comment', '')
        user_id = request.current_user.id if hasattr(request, 'current_user') else None
        
        # 确认告警
        success = db_service.confirm_alert(alert_id, user_id=user_id, comment=comment)
        
        if success:
            # 同时更新内存中的告警状态
            alert_manager.confirm_alert(alert_id)
            
            return jsonify({
                'success': True,
                'data': None,
                'message': '告警确认成功'
            })
        else:
            return jsonify({
                'success': False,
                'data': None,
                'message': '告警不存在或状态错误'
            }), 404
            
    except Exception as e:
        logger.error(f"确认告警失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'确认告警失败: {str(e)}'
        }), 500


@alerts_bp.route('/<int:alert_id>/resolve', methods=['POST'])
@token_required
@log_api_access
def resolve_alert(alert_id):
    """解决告警"""
    try:
        # 解析请求体
        data = request.get_json() or {}
        comment = data.get('comment', '')
        user_id = request.current_user.id if hasattr(request, 'current_user') else None
        
        # 解决告警
        success = db_service.resolve_alert(alert_id, user_id=user_id, comment=comment)
        
        if success:
            # 同时更新内存中的告警状态
            alert_manager.resolve_alert(alert_id)
            
            return jsonify({
                'success': True,
                'data': None,
                'message': '告警解决成功'
            })
        else:
            return jsonify({
                'success': False,
                'data': None,
                'message': '告警不存在或状态错误'
            }), 404
            
    except Exception as e:
        logger.error(f"解决告警失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'解决告警失败: {str(e)}'
        }), 500


@alerts_bp.route('/<int:alert_id>/read', methods=['PATCH'])
@token_required
@log_api_access
def mark_alert_read(alert_id):
    """标记告警为已读"""
    try:
        # 标记为已确认
        success = db_service.update_alert_acknowledged_status(alert_id, True)
        
        if success:
            return jsonify({
                'success': True,
                'data': None,
                'message': '告警已标记为已读'
            })
        else:
            return jsonify({
                'success': False,
                'data': None,
                'message': '告警不存在'
            }), 404
            
    except Exception as e:
        logger.error(f"标记告警为已读失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'标记告警为已读失败: {str(e)}'
        }), 500


@alerts_bp.route('/batch/read', methods=['POST'])
@token_required
@log_api_access
def batch_mark_alerts_read():
    """批量标记告警为已读"""
    try:
        # 解析请求体
        data = request.get_json() or {}
        alert_ids = data.get('alert_ids', [])
        
        if not isinstance(alert_ids, list) or not alert_ids:
            return jsonify({
                'success': False,
                'data': None,
                'message': '请提供有效的告警ID列表'
            }), 400
        
        # 批量标记为已确认
        count = db_service.batch_update_alert_acknowledged_status(alert_ids, True)
        
        return jsonify({
            'success': True,
            'data': {
                'updated_count': count
            },
            'message': f'成功标记{count}条告警为已读'
        })
        
    except Exception as e:
        logger.error(f"批量标记告警为已读失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'批量标记告警为已读失败: {str(e)}'
        }), 500


@alerts_bp.route('/batch/confirm', methods=['POST'])
@token_required
@log_api_access
def batch_confirm_alerts():
    """批量确认告警"""
    try:
        # 解析请求体
        data = request.get_json() or {}
        alert_ids = data.get('alert_ids', [])
        comment = data.get('comment', '')
        user_id = request.current_user.id if hasattr(request, 'current_user') else None
        
        if not isinstance(alert_ids, list) or not alert_ids:
            return jsonify({
                'success': False,
                'data': None,
                'message': '请提供有效的告警ID列表'
            }), 400
        
        # 批量确认告警
        count = db_service.batch_confirm_alerts(alert_ids, user_id=user_id, comment=comment)
        
        # 更新内存中的告警状态
        for alert_id in alert_ids:
            alert_manager.confirm_alert(alert_id)
        
        return jsonify({
            'success': True,
            'data': {
                'updated_count': count
            },
            'message': f'成功确认{count}条告警'
        })
        
    except Exception as e:
        logger.error(f"批量确认告警失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'批量确认告警失败: {str(e)}'
        }), 500


@alerts_bp.route('/alerts/statistics', methods=['GET'])
@token_required
@log_api_access
def get_alert_statistics():
    """获取告警统计信息
    
    查询参数:
    - period: 统计周期(day, week, month, year), 默认day
    - days: 过去多少天, 默认7
    """
    try:
        # 解析查询参数
        period = request.args.get('period', 'day')
        days = int(request.args.get('days', 7))
        
        # 计算时间范围
        end_date = datetime.now()
        start_date = end_date - timedelta(days=days)
        
        # 获取统计数据
        stats = db_service.get_alert_statistics(
            start_date=start_date,
            end_date=end_date,
            period=period
        )
        
        return jsonify({
            'success': True,
            'data': {
                'overview': stats.get('overview', {}),
                'by_type': stats.get('by_type', []),
                'by_severity': stats.get('by_severity', []),
                'by_camera': stats.get('by_camera', []),
                'time_series': stats.get('time_series', []),
                'start_date': start_date.isoformat(),
                'end_date': end_date.isoformat()
            },
            'message': '告警统计信息获取成功'
        })
        
    except Exception as e:
        logger.error(f"获取告警统计信息失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'获取告警统计信息失败: {str(e)}'
        }), 500


@alerts_bp.route('/alerts/unread/count', methods=['GET'])
@token_required
@log_api_access
def get_unread_alert_count():
    """获取未读告警数量"""
    try:
        # 获取未读告警数量
        count = db_service.get_unread_alert_count()
        
        return jsonify({
            'success': True,
            'data': {
                'unread_count': count
            },
            'message': '未读告警数量获取成功'
        })
        
    except Exception as e:
        logger.error(f"获取未读告警数量失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'获取未读告警数量失败: {str(e)}'
        }), 500


@alerts_bp.route('/alerts/<int:alert_id>/image', methods=['GET'])
@token_required
@log_api_access
def get_alert_image(alert_id):
    """获取告警关联的图片"""
    try:
        # 获取告警信息
        alert = db_service.get_alert_by_id(alert_id)
        if not alert:
            return jsonify({
                'success': False,
                'data': None,
                'message': '告警不存在'
            }), 404
        
        # 检查是否有图片
        if not alert.image_path:
            return jsonify({
                'success': False,
                'data': None,
                'message': '该告警没有关联图片'
            }), 404
        
        # 获取图片的Base64编码
        try:
            import base64
            with open(alert.image_path, 'rb') as f:
                image_data = f.read()
                base64_image = base64.b64encode(image_data).decode('utf-8')
            
            # 确定图片类型
            import os
            ext = os.path.splitext(alert.image_path)[1].lower()
            if ext == '.jpg' or ext == '.jpeg':
                mime_type = 'image/jpeg'
            elif ext == '.png':
                mime_type = 'image/png'
            else:
                mime_type = 'image/jpeg'
            
            return jsonify({
                'success': True,
                'data': {
                    'image': base64_image,
                    'mime_type': mime_type,
                    'filename': os.path.basename(alert.image_path)
                },
                'message': '告警图片获取成功'
            })
            
        except Exception as img_err:
            logger.error(f"读取告警图片失败: {str(img_err)}")
            return jsonify({
                'success': False,
                'data': None,
                'message': '告警图片读取失败'
            }), 500
            
    except Exception as e:
        logger.error(f"获取告警图片失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'获取告警图片失败: {str(e)}'
        }), 500


@alerts_bp.route('/alerts/types', methods=['GET'])
@token_required
@log_api_access
def get_alert_types():
    """获取所有告警类型信息"""
    try:
        # 获取告警类型配置
        alert_types = []
        for alert_type in AlertType:
            alert_types.append({
                'value': alert_type.value,
                'name': AlertType.get_alert_name(alert_type.value),
                'description': AlertType.get_alert_description(alert_type.value),
                'category': AlertType.get_alert_category(alert_type.value),
                'default_severity': AlertType.get_default_severity(alert_type.value)
            })
        
        return jsonify({
            'success': True,
            'data': {
                'alert_types': alert_types
            },
            'message': '告警类型信息获取成功'
        })
        
    except Exception as e:
        logger.error(f"获取告警类型信息失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'获取告警类型信息失败: {str(e)}'
        }), 500


@alerts_bp.route('/alerts/<int:alert_id>/comment', methods=['POST'])
@token_required
@log_api_access
def add_alert_comment(alert_id):
    """添加告警评论"""
    try:
        # 解析请求体
        data = request.get_json() or {}
        comment = data.get('comment', '')
        
        if not comment:
            return jsonify({
                'success': False,
                'data': None,
                'message': '评论内容不能为空'
            }), 400
        
        user_id = request.current_user.id if hasattr(request, 'current_user') else None
        
        # 添加评论
        comment_id = db_service.add_alert_comment(alert_id, comment, user_id)
        
        if comment_id:
            return jsonify({
                'success': True,
                'data': {
                    'comment_id': comment_id
                },
                'message': '评论添加成功'
            })
        else:
            return jsonify({
                'success': False,
                'data': None,
                'message': '告警不存在'
            }), 404
            
    except Exception as e:
        logger.error(f"添加告警评论失败: {str(e)}")
        return jsonify({
            'success': False,
            'data': None,
            'message': f'添加告警评论失败: {str(e)}'
        }), 500